/**
 * @author Shine
 */
package com.shine.crypt
{
	import com.shine.crypt.ArrayBase;
	import com.shine.ports.IAnimationClip;
	import com.shine.utils.BitmapUtil;
	import com.shine.utils.ClassUtil;
	import com.shine.utils.DisplayObjectUtil;
	import com.shine.utils.StringUtil;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MovieClip;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class BitmapMovie extends AnimationClip implements IAnimationClip
	{
		protected var _cacheAsBitmap:Boolean=false;
		protected var _min_x:Number=int.MAX_VALUE;
		protected var _min_y:Number=int.MAX_VALUE;
		
		public var makeupValue:uint=0;
		
		public function BitmapMovie()
		{
			super();
		}
		
		public function set cacheAsBitmap(b:Boolean):void
		{
			if(_cacheAsBitmap==b)return;
			_cacheAsBitmap=b;
			if(!_cacheAsBitmap) return;
			
			var temp_cache:ArrayBase =new ArrayBase();
			var temp_frames:ArrayBase=new ArrayBase();
			
			for each (var obj:DisplayObject in _cache) { 
				temp_cache.push(obj); 
			} 
			
			for each (var m:uint in _frames) { 
				temp_frames.push(m); 
			} 

			_cache=new Vector.<DisplayObject>();
			_frames=new Vector.<uint>();
			
			for(var i:uint=0;i<temp_cache.length;i++){
				var item:DisplayObject=temp_cache[i];
				if(item==null){
					var temp_arr:ArrayBase=temp_frames.search(i);
					var temp_num:uint=temp_arr==null ? 1 : temp_arr.length;
					var temp_id:int=_cache.push(item);
					while(temp_num>0){_frames.push(temp_id-1);temp_num--};
					continue;
				}
				
				if(!(item is Bitmap)){
					var list:Vector.<Bitmap>=changeToBitmap(item);
					var arr:ArrayBase=temp_frames.search(i);
					var num:uint=arr==null ? 1 : arr.length;
					var count:uint=0;
					for(var j:uint=0;j<list.length;j++){
						var id:int=_cache.push(list[j]);
						
						if(item is MovieClip){
							_frames.push(id-1);
							count++;
							
							if(num>list.length && count>=list.length){
								num-=list.length;
							}else{
								continue;
							}
						}
						
						while(num>0)
						{
							_frames.push(id-1);num--
						}
						
					}
				}
			}
			
		}
		
		public function get cacheAsBitmap():Boolean
		{
			return _cacheAsBitmap;
		}
		
		public function set displayBoundsRect(b:Boolean):void
		{
			_container.graphics.clear();
			if(!b || !_enabled || !_cacheAsBitmap)return;
			_container.graphics.lineStyle(1,0xFFFF00);
			_container.graphics.drawRect(_min_x,_min_y,maxWidth,maxHeight);
		}
		
		public function addBitmapDatas(list:Vector.<BitmapData>,frames:String="",sign:String="#"):void
		{
			if(list==null || list.length<1)return;
			var arr:Array=StringUtil.isEmpty(frames) ? null : frames.split(sign);
			
			for(var i:uint;i<list.length;i++){
				var frame:uint=arr==null ? 1 : uint(arr[i]);
				try{
					addChild(new Bitmap(list[i],"auto",true),frame);
				}catch(e:Error){
					trace("BitmapMovie:addBitmapDatas error "+e.message);
				}
			}
		}
		
		public function removeFromArray(arr:Array):void
		{
			for(var i:uint=0;i<arr.length;i++){
				if(!this.removeChildAt(arr[i])) trace("BitmapMovie:removeChildFromArray can't find id for "+arr[i]);
			}
		}
		
		override public function addChild(child:DisplayObject,frames:uint=1):Array
		{
			var arr:Array=new Array();
			if(!_cacheAsBitmap || (child is Bitmap)){
				return super.addChild(child,frames);
			}else{
				check_MC_label(child);
				if(child!=null){
					var list:Vector.<Bitmap>=changeToBitmap(child);
					var count:uint=0;
					for(var j:uint=0;j<list.length;j++){
						var id:int=_cache.push(list[j]);
						arr.push(id-1);
						resetSizeValue(list[j]);
						if(child is MovieClip){
							_frames.push(id-1);
							count++;
							
							if(frames>list.length && count>=list.length){
								frames-=list.length;
							}else{
								continue;
							}
						}
						while(frames>0){_frames.push(id-1);frames--};
					}
				}else{
					id=_cache.push(child);
					while(frames>0){_frames.push(id-1);frames--};
					arr.push(id-1);
				}
				addDirectPoint();
			}
			return arr;
		}
		
		protected function changeToBitmap(obj:DisplayObject):Vector.<Bitmap>
		{
			var list:Vector.<Bitmap>=new Vector.<Bitmap>();
			if(obj is MovieClip){
				var mc:MovieClip=obj as MovieClip;
				var filters:Array=mc.filters;
				var rect:Rectangle;
				var maxX:int=0;
				var maxY:int=0;
				var minX:int=int.MAX_VALUE;
				var minY:int=int.MAX_VALUE;
				
				for(var j:uint=0;j<mc.totalFrames;j++){
					mc.gotoAndStop(j+1);
					rect=DisplayObjectUtil.getContainerRect(mc);
					minX=Math.min(int(rect.x),minX);
					minY=Math.min(int(rect.y),minY);
					maxX=Math.max(int(rect.bottomRight.x),maxX);
					maxY=Math.max(int(rect.bottomRight.y),maxY);
				}
				
				var space_x:int=makeupValue;
				var space_y:int=makeupValue;
				var bmd:BitmapData=new BitmapData(uint(maxX-minX),uint(maxY-minY), true, 0);
				
				for(var k:uint=0;k<filters.length;k++){
					rect= bmd.generateFilterRect(bmd.rect, filters[k]);
					space_x=Math.max(-rect.x,space_x);
					space_y=Math.max(-rect.y,space_y);
				}
				
				minX-=space_x;
				minY-=space_y;
				maxX+=space_x;
				maxY+=space_y;
				//trace(minX,minY,maxX,maxY);
				
				var _store:ArrayBase=new ArrayBase();
				for(var i:uint=1;i<=mc.totalFrames;i++){
					mc.gotoAndStop(i);
					playChildMC(mc,i,_store);
					var data:BitmapData=BitmapUtil.toBitmapData(mc,uint(maxX-minX),uint(maxY-minY),minX,minY);
					var bm:Bitmap=new Bitmap(data,"auto",true);
					bm.x=minX;
					bm.y=minY;
					list.push(bm);
				}
                
				_store=null;
				_min_x=Math.min(_min_x,minX);
				_min_y=Math.min(_min_y,minY);
			}else{
				list.push(new Bitmap(BitmapUtil.toBitmapData(obj),"auto",true));
			}
			return list;
		}
		
		protected function playChildMC(mc:MovieClip,frame:uint,store:ArrayBase):void
		{
			var list:Array=DisplayObjectUtil.getAllChildMC(mc);
			for(var i:uint=0;i<list.length;i++){
				var item:MovieClip=list[i] as MovieClip;
				if(item==null)continue;
				var index:int=store.indexByProperty("mc",item);
				if(index==-1){
					store.push({mc:item,n:frame});
					item.gotoAndPlay(1);
				}else{
					var j:int=(frame-store[index].n)%item.totalFrames;
					item.gotoAndPlay(j<1 ? 1 : j);
				}
			}
		}
		
		override public function clone(C:Class=null):IAnimationClip
		{
			if(!_cacheAsBitmap) return super.clone((C==null) ? BitmapMovie : C);
			
			var copy:BitmapMovie=new BitmapMovie();
			copy.cacheAsBitmap=true;
			copy.loop=loop;
			DisplayObjectUtil.copyAttribute(copy.container,container);
			
			for(var i:uint=0;i<_cache.length;i++){
				var l:int=getTargetLength(i);
				if(l!=-1){
					var item:Bitmap=_cache[i] as Bitmap;
					if(item==null){
						copy.addChild(item,l);
					}else{
						var child:Bitmap=new Bitmap(item.bitmapData.clone(),"auto",true);
						DisplayObjectUtil.copyAttribute(child,item);
						copy.addChild(child,l);
					}
				}
			}
			return copy;
		}
		
		override public function toString():String
		{
			return ClassUtil.toString(this,"cacheAsBitmap","makeupValue","currentFrame","totalFrames","maxWidth","maxHeight","container","loop");
		}
	}
}